home *** CD-ROM | disk | FTP | other *** search
- #define MAXPATHLEN 1024
-
- #include <strings.h>
- #include <stdio.h>
- #include <pwd.h>
-
- #include "utils/log.h"
- #include "catalogutils.h"
- #include "nodes/pg_lisp.h"
- #include "utils/exc.h"
- #include "utils/excid.h"
- #include "io.h"
- #include "utils/palloc.h"
- #include "parse_query.h"
- #include "catalog/pg_aggregate.h"
- #include "nodes/primnodes.h"
- #include "nodes/primnodes.a.h"
- #include "nodes/plannodes.h"
- #include "nodes/plannodes.a.h"
- #include "nodes/execnodes.h"
- #include "nodes/execnodes.a.h"
- #include "nodes/relation.h"
- #include "nodes/relation.a.h"
- #include "parser/parse.h"
- #include "parser/parsetree.h"
- #include "utils/builtins.h"
- #include "lib/lisplist.h"
-
- RcsId("$Header: /private/postgres/src/parser/RCS/ylib.c,v 1.78 1992/07/10 15:48:15 mao Exp $");
-
- LispValue parsetree;
-
- #define DB_PARSE(foo)
-
- parser(str, l, typev, nargs)
- char *str;
- LispValue l;
- ObjectId *typev;
- int nargs;
- {
- int yyresult;
- void DeleteBuffer(void);
-
- init_io();
-
- /* Set things up to read from the string, if there is one */
- if (strlen(str) != 0) {
- StringInput = 1;
- TheString = (char *) palloc(strlen(str) + 1);
- bcopy(str,TheString,strlen(str)+1);
- }
-
- parser_init(typev, nargs);
- yyresult = yyparse();
- DeleteBuffer();
-
- clearerr(stdin);
-
- if (yyresult) { /* error */
- CAR(l) = LispNil;
- CDR(l) = LispNil;
- return(-1);
- }
-
- CAR(l) = CAR(parsetree);
- CDR(l) = CDR(parsetree);
-
- if (parsetree == NULL) {
- return(-1);
- } else {
- return(0);
- }
- }
-
- LispValue
- new_filestr ( filename )
- LispValue filename;
- {
- return (lispString (filename_in (CString(filename))));
- }
-
- int
- lispAssoc ( element, list)
- LispValue element, list;
- {
- LispValue temp = list;
- int i = 0;
- if (list == LispNil)
- return -1;
- /* printf("Looking for %d", CInteger(element));*/
-
- while (temp != LispNil ) {
- if(CInteger(CAR(temp)) == CInteger(element))
- return i;
- temp = CDR(temp);
- i ++;
- }
-
- return -1;
- }
-
- LispValue
- parser_typecast ( expr, typename )
- LispValue expr;
- LispValue typename;
- {
- /* check for passing non-ints */
- Const adt;
- Datum lcp;
- Type tp;
- char *type_string, *p, type_string_2[16];
- int32 len;
- char *cp = NULL;
- char *const_string;
- bool string_palloced = false;
-
- type_string = CString(CAR(typename));
- if (CDR(typename) != LispNil) {
- *p = 0;
- sprintf(type_string_2,"_%s", type_string);
- tp = (Type) type(type_string_2);
- } else {
- tp = (Type) type(type_string);
- }
-
- len = tlen(tp);
-
- switch ( CInteger(CAR(expr)) ) {
- case 23: /* int4 */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%d", get_constvalue((Const)CDR(expr)));
- break;
-
- case 19: /* char16 */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%s", get_constvalue((Const)CDR(expr)));
- break;
-
- case 18: /* char */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%c", get_constvalue((Const)CDR(expr)));
- break;
-
- case 701:/* float8 */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%f", get_constvalue((Const)CDR(expr)));
- break;
-
- case 25: /* text */
- const_string = DatumGetPointer(get_constvalue((Const)CDR(expr)));
- const_string = (char *) textout((struct varlena *)const_string);
- break;
-
- case 705: /* unknown */
- const_string = DatumGetPointer(get_constvalue((Const)CDR(expr)));
- const_string = (char *) textout((struct varlena *)const_string);
- break;
-
- default:
- elog(WARN,"unknown type %d", CInteger(CAR(expr)));
- }
-
- cp = instr2 (tp, const_string);
-
- if (!tbyvalue(tp)) {
- if (len >= 0 && len != PSIZE(cp)) {
- char *pp;
- pp = (char *) palloc(len);
- bcopy(cp, pp, len);
- cp = pp;
- }
- lcp = PointerGetDatum(cp);
- } else {
- switch(len) {
- case 1:
- lcp = Int8GetDatum(cp);
- break;
- case 2:
- lcp = Int16GetDatum(cp);
- break;
- case 4:
- lcp = Int32GetDatum(cp);
- break;
- default:
- lcp = PointerGetDatum(cp);
- break;
- }
- }
-
- adt = MakeConst ( typeid(tp), len, (Datum)lcp , 0, 0/*was omitted*/ );
-
- if (string_palloced)
- pfree(const_string);
-
- return (lispCons(lispInteger(typeid(tp)), (LispValue)adt));
- }
-
- LispValue
- parser_typecast2 ( expr, tp)
- LispValue expr;
- Type tp;
- {
- /* check for passing non-ints */
- Const adt;
- Datum lcp;
- int32 len = tlen(tp);
- char *cp = NULL;
-
- char *const_string;
- bool string_palloced = false;
-
- switch ( CInteger(CAR(expr)) ) {
- case 23: /* int4 */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%d",
- get_constvalue((Const)CDR(expr)));
- break;
- case 19: /* char16 */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%s",
- get_constvalue((Const)CDR(expr)));
- break;
- case 18: /* char */
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%c",
- get_constvalue((Const)CDR(expr)));
- break;
- case 701:/* float8 */
- {
- float64 floatVal =
- DatumGetFloat64(get_constvalue((Const)CDR(expr)));
- const_string = (char *) palloc(256);
- string_palloced = true;
- sprintf(const_string,"%f", *floatVal);
- break;
- }
- case 25: /* text */
- const_string =
- DatumGetPointer(
- get_constvalue((Const)CDR(expr)) );
- const_string = (char *) textout((struct varlena *)const_string);
- break;
- case 705: /* unknown */
- const_string =
- DatumGetPointer(
- get_constvalue((Const)CDR(expr)) );
- const_string = (char *) textout((struct varlena *)const_string);
- break;
- default:
- elog(WARN,"unknown type%d ",
- CInteger(CAR(expr)) );
- }
-
- cp = instr2 (tp, const_string);
-
-
- if (!tbyvalue(tp)) {
- if (len >= 0 && len != PSIZE(cp)) {
- char *pp;
- pp = (char *) palloc(len);
- bcopy(cp, pp, len);
- cp = pp;
- }
- lcp = PointerGetDatum(cp);
- } else {
- switch(len) {
- case 1:
- lcp = Int8GetDatum(cp);
- break;
- case 2:
- lcp = Int16GetDatum(cp);
- break;
- case 4:
- lcp = Int32GetDatum(cp);
- break;
- default:
- lcp = PointerGetDatum(cp);
- break;
- }
- }
-
- adt = MakeConst ( (ObjectId)typeid(tp), (Size)len, (Datum)lcp , 0 , 0/*was omitted*/);
- /*
- printf("adt %s : %d %d %d\n",CString(expr),typeid(tp) ,
- len,cp);
- */
- if (string_palloced) pfree(const_string);
- return ((LispValue) adt);
- }
-
- char *
- after_first_white_space( input )
- char *input;
- {
- char *temp = input;
- while ( *temp != ' ' && *temp != 0 )
- temp = temp + 1;
-
- return (temp+1);
- }
-
- int
- *int4varin( input_string )
- char *input_string;
- {
- int *foo = (int *)malloc(1024*sizeof(int));
- register int i = 0;
-
- char *temp = input_string;
-
- while ( sscanf(temp,"%ld", &foo[i+1]) == 1
- && i < 1022 ) {
- i = i+1;
- temp = after_first_white_space(temp);
- }
- foo[0] = i;
- return(foo);
- }
-
- char *
- int4varout ( an_array )
- int *an_array;
- {
- int temp = an_array[0];
- char *output_string = NULL;
- extern int itoa();
- int i;
-
- if ( temp > 0 ) {
- char *walk;
- output_string = (char *)malloc(16*temp); /* assume 15 digits + sign */
- walk = output_string;
- for ( i = 0 ; i < temp ; i++ ) {
- itoa(an_array[i+1],walk);
- printf ( "%s\n", walk );
- while (*++walk != '\0')
- ;
- *walk++ = ' ';
- }
- *--walk = '\0';
- }
- return(output_string);
- }
-
-
- #define ADD_TO_RT(rt_entry) p_rtable = nappend1(p_rtable,rt_entry)
- extern List p_rtable;
- List
- ParseFunc ( funcname , fargs )
- char *funcname;
- List fargs;
- {
- OID rettype = (OID)0;
- OID funcid = (OID)0;
- OID argrelid;
- LispValue i = LispNil;
- List first_arg_type = NULL;
- Name relname, oldname;
- Relation rd;
- ObjectId relid;
- int attnum;
- int nargs;
- Iter iter;
- Func funcnode;
- ObjectId oid_array[8];
- OID argtype;
- Param f;
- int vnum;
- LispValue retval;
- LispValue setup_base_tlist();
- bool retset;
- bool exists;
-
- if (fargs)
- {
- if (CAR(fargs) == LispNil)
- elog (WARN,"function %s does not allow NULL input",funcname);
- first_arg_type = CAR(CAR(fargs));
- }
-
- /*
- ** check for projection methods: if function takes one argument, and
- ** that argument is a relation, param, or PQ function returning a complex
- ** type, then the function could be a projection.
- */
- if (length(fargs) == 1)
- {
- if (lispAtomp(first_arg_type) && CAtom(first_arg_type) == RELATION)
- {
- /* this is could be a projection */
- relname = (Name) CString(CDR(CAR(fargs)));
- if( RangeTablePosn ( relname ,LispNil ) == 0 )
- ADD_TO_RT( MakeRangeTableEntry ((Name)relname,
- LispNil,
- (Name)relname ));
- oldname = relname;
- relname = VarnoGetRelname(RangeTablePosn(oldname,0));
- rd = heap_openr(relname);
- relid = RelationGetRelationId(rd);
- heap_close(rd);
- if ((attnum = get_attnum(relid, (Name) funcname))
- != InvalidAttributeNumber)
- return((LispValue)(make_var(oldname, funcname)));
- else /* drop through */;
- }
- else if (ISCOMPLEX(CInteger(first_arg_type)) &&
- IsA(CDR(CAR(fargs)),Iter) &&
- (argrelid = typeid_get_relid
- ((int)(argtype=funcid_get_rettype
- (get_funcid((Func)(CAR(get_iterexpr((Iter)CDR(CAR(fargs)))))))))))
- {
- /* the argument is a function returning a tuple, so funcname
- may be a projection */
- if ((attnum = get_attnum(argrelid, (Name) funcname))
- != InvalidAttributeNumber)
- {
- /* add a tlist to the func node and return the Iter */
- rd = heap_openr(tname(get_id_type(argtype)));
- if (RelationIsValid(rd))
- {
- relid = RelationGetRelationId(rd);
- relname = RelationGetRelationName(rd);
- heap_close(rd);
- }
- if (RelationIsValid(rd))
- {
- iter = (Iter)CDR(CAR(fargs));
- set_func_tlist((Func)CAR(get_iterexpr(iter)),
- setup_tlist(funcname, argrelid));
- return(lispCons(lispInteger(att_typeid(rd,attnum)),iter));
- }
- else elog(WARN,
- "Function %s has bad returntype %d",
- funcname, argtype);
- }
- else /* drop through */;
- }
- else if (ISCOMPLEX(CInteger(first_arg_type)) &&
- IsA(CADR(CAR(fargs)),Func) &&
- (argrelid = typeid_get_relid
- ((int)(argtype=funcid_get_rettype
- (get_funcid((Func)CADR(CAR(fargs))))))))
- {
- /* the argument is a function returning a tuple, so funcname
- may be a projection */
- if ((attnum = get_attnum(argrelid, (Name) funcname))
- != InvalidAttributeNumber)
- {
- /* add a tlist to the func node */
- rd = heap_openr(tname(get_id_type(argtype)));
- if (RelationIsValid(rd))
- {
- relid = RelationGetRelationId(rd);
- relname = RelationGetRelationName(rd);
- heap_close(rd);
- }
- if (RelationIsValid(rd))
- {
- funcnode = (Func)CADR(CAR(fargs));
- set_func_tlist(funcnode,
- setup_tlist(funcname, argrelid));
- return(lispCons(lispInteger(att_typeid(rd,attnum)),
- CDR(CAR(fargs))));
- }
- else elog(WARN,
- "Function %s has bad returntype %d",
- funcname, argtype);
- }
- else /* drop through */;
- }
- else if (ISCOMPLEX(CInteger(first_arg_type)) &&
- IsA(CADR(CAR(fargs)),Param))
- {
- /* If the Param is a complex type, this could be a projection */
- f = (Param)CADR(CAR(fargs));
- rd = heap_openr(tname(get_id_type(get_paramtype(f))));
- if (RelationIsValid(rd))
- {
- relid = RelationGetRelationId(rd);
- relname = RelationGetRelationName(rd);
- heap_close(rd);
- }
- if (RelationIsValid(rd) &&
- (attnum = get_attnum(relid, (Name) funcname))
- != InvalidAttributeNumber)
- {
- set_param_tlist(f, setup_tlist(funcname, relid));
- return(lispCons(lispInteger(att_typeid(rd, attnum)), f));
- }
- else /* drop through */;
- }
- }
-
-
- /*
- ** If we dropped through to here it's really a function.
- ** extract arg type info and transform relation name arguments into
- ** varnodes of the appropriate form.
- */
-
- bzero(&oid_array[0], 8 * sizeof(ObjectId));
- nargs=0;
-
- foreach ( i , fargs )
- {
- List pair = CAR(i);
- ObjectId toid;
-
- if (lispAtomp(CAR(pair)) && CAtom(CAR(pair)) == RELATION)
- {
- relname = (Name)CString(CDR(pair));
-
- /* get the range table entry for the var node */
- vnum = RangeTablePosn(relname, 0);
- if (vnum == 0) {
- p_rtable = nappend1(p_rtable ,
- MakeRangeTableEntry(relname, 0, relname));
- vnum = RangeTablePosn (relname, 0);
- }
-
- /*
- * We have to do this because the relname in the pair
- * may have been a range table variable name, rather
- * than a real relation name.
- */
-
- relname = (Name) VarnoGetRelname(vnum);
-
- rd = heap_openr(relname);
- relid = RelationGetRelationId(rd);
- heap_close(rd);
- toid = typeid(type(relname));
-
- /*
- * for func(relname), the param to the function
- * is the tuple under consideration. we build a special
- * VarNode to reflect this -- it has varno set to the correct
- * range table entry, but has varattno == 0 to signal that the
- * whole tuple is the argument.
- */
-
- CAR(i) = (LispValue)
- MakeVar(vnum, 0, toid,
- lispCons(lispInteger(vnum),
- lispCons(lispInteger(0),LispNil)),
- 0 /* varslot */);
- }
- else
- {
- toid = CInteger(CAR(pair));
- CAR(i) = CDR(pair);
- }
-
- oid_array[nargs++] = toid;
- }
-
- /*
- * func_get_detail looks up the function in the catalogs, does
- * disambiguation for polymorphic functions, handles inheritance,
- * and returns the funcid and type and set or singleton status of
- * the function's return value. if func_get_detail returns true,
- * the function exists. otherwise, there was an error.
- */
-
- exists = func_get_detail(funcname, nargs, oid_array, &funcid,
- &rettype, &retset);
- if (!exists)
- elog(WARN, "no such attribute or function %s", funcname);
-
- /* got it */
- funcnode = MakeFunc(funcid, rettype, false, 0, LispNil, 0, NULL, LispNil, LispNil);
-
- /*
- * for functons returning base types, we want to project out the
- * return value. set up a target list to do that. the executor
- * will ignore these for c functions, and do the right thing for
- * postquel functions.
- */
-
- if (typeid_get_relid(rettype) == InvalidObjectId)
- set_func_tlist(funcnode, (LispValue)setup_base_tlist(rettype));
-
- retval = lispCons((LispValue) funcnode, fargs);
-
- /*
- * if the function returns a set of values, then we need to iterate
- * over all the returned values in the executor, so we stick an
- * iter node here. if it returns a singleton, then we don't need
- * the iter node.
- */
-
- if (retset)
- retval = (LispValue) MakeIter(retval);
-
- /* store type info in the return value for use by the type checker */
- retval = lispCons (lispInteger(rettype), retval);
-
- return(retval);
- }
-
- List
- ParseAgg(aggname, query, tlist)
- char *aggname;
- List query;
- List tlist;
- {
- int fintype;
- OID AggId = (OID)0;
- List list = LispNil;
- char *keyword = "agg";
- HeapTuple theAggTuple;
- tlist = CADR(tlist);
- if(!query)
- elog(WARN,"aggregate %s called without arguments", aggname);
- theAggTuple = SearchSysCacheTuple(AGGNAME, aggname, 0, 0, 0);
- AggId = (theAggTuple ? theAggTuple->t_oid : (OID)0);
-
- if(AggId == (OID)0) {
- elog(WARN, "aggregate %s does not exist", aggname);
- }
- fintype = CInteger((LispValue)SearchSysCacheGetAttribute(AGGNAME,
- AggregateFinalTypeAttributeNumber, aggname, 0, 0, 0));
-
- if(fintype != 0 ) {
- list = (LispValue)
- MakeList(lispInteger(fintype),lispName(keyword),lispName(aggname),
- query,tlist,-1);
- } else
- elog(WARN, "aggregate %s does not exist", aggname);
-
- return (list);
- }
-
-
- /*
- * RemoveUnusedRangeTableEntries
- * - removes relations from the rangetable that are no longer
- * useful. This helps in preventing the planner from generating
- * extra joins that are not needed.
- */
-
- /* XXX - not used yet
-
- List
- RemoveUnusedRangeTableEntries ( parsetree )
- List parsetree;
- {
-
- }
- */
-
- /*
- * FlattenRelationList
- *
- * at this point, time-qualified relation/relation-lists
- * have a lispInteger in the front,
- * inheritance relations have a lispString("*")
- * in front
- */
-
-
- #ifdef NOTYET
- XXX - not used yet
-
- List
- FlattenRelationList ( rel_list )
- List rel_list;
- {
- List temp = NULL;
- List possible_rtentry = NULL;
-
- foreach ( temp, rel_list ) {
- possible_rtentry = CAR(temp);
-
- if ( consp ( possible_rtentry ) ) {
-
- /* can be any one of union, inheritance or timerange queries */
-
- } else {
- /* normal entry */
-
- }
- }
- }
-
- #endif
-
- List
- MakeFromClause ( from_list, base_rel )
- List from_list;
- LispValue base_rel;
- {
- List i = NULL;
- List j = NULL;
- List k = NULL;
- List flags = NULL;
- List entry = NULL;
- bool IsConcatenation = false;
- List existing_varnos = NULL;
- extern List RangeTablePositions();
-
- /* from_list will be a list of strings */
- /* base_rel will be a wierd assortment of things,
- including timerange, inheritance and union relations */
-
- if ( length ( base_rel ) > 1 ) {
- IsConcatenation = true;
- }
-
- foreach ( i , from_list ) {
- List temp = CAR(i);
-
- foreach ( j , base_rel ) {
- List x = CAR(j);
-
- /* now reinitialize "flags" so that we don't
- * get inheritance or time range queries for
- * relations that we didn't want them on
- */
-
- flags = lispCons(lispInteger(0),LispNil);
-
- if ( IsConcatenation == true ) {
- flags = nappend1(flags, lispAtom("union"));
- }
- if ( ! null ( CADDR(x))) {
- flags = nappend1(flags, lispAtom("inherits"));
- }
-
- if ( ! null ( CADR(x))) {
- /* set time range, if one exists */
- CAR(flags) = CADR(x);
- }
-
- existing_varnos =
- RangeTablePositions ( CString( CAR(x)), LispNil );
- /* XXX - 2nd argument is currently ignored */
-
- if ( existing_varnos == NULL ) {
- /* if the base relation does not exist in the rangetable
- * as a virtual name, make a new rangetable entry
- */
- entry = (List)MakeRangeTableEntry ( (Name)CString ( CAR(x)),
- flags ,
- (Name)CString(temp));
- ADD_TO_RT(entry);
- } else {
- /* XXX - temporary, should append the existing flags
- * to the new flags or not ?
- */
- foreach(k,existing_varnos) {
- int existing_varno = CInteger(CAR(k));
- List rt_entry = nth ( existing_varno-1 , p_rtable );
- if ( IsA(CAR(rt_entry),LispStr)) {
- /* first time consing it */
- CAR(rt_entry) = lispCons ( CAR(rt_entry) ,
- lispCons (temp,LispNil ));
- } else {
- /* subsequent consing */
- CAR(rt_entry) = nappend1 ( CAR(rt_entry) , temp);
- }
- /* in either case, if no union flag exists,
- * cons one in
- */
- rt_flags (rt_entry) = nappend1 ( rt_flags(rt_entry),
- lispAtom("union"));
- } /* foreach k */
-
- } /* if existing_varnos == NULL */
-
- /* NOTE : we dont' pfree old "flags" because they are
- * really still present in the parsetree
- */
-
- } /* foreach j */
- } /* foreach i */
-
- return ( entry );
- }
-
- /*
- ** HandleNestedDots --
- ** Given a nested dot expression (i.e. (relation func ... attr), build up
- ** a tree with of Iter and Func nodes.
- */
- LispValue HandleNestedDots(dots)
- List dots;
- {
- List mutator_iter;
- LispValue retval = LispNil;
-
- if (IsA(CAR(dots),Param))
- retval =
- ParseFunc(CString(CADR(dots)),
- lispCons(MakeList
- (lispInteger(get_paramtype((Param)CAR(dots))),
- CAR(dots), -1),
- LispNil));
- else
- retval = ParseFunc(CString(CADR(dots)),
- lispCons(lispCons(lispAtom("relation"),
- CAR(dots)),
- LispNil));
-
- foreach (mutator_iter, CDR(CDR(dots)))
- retval = ParseFunc(CString(CAR(mutator_iter)), lispCons(retval, LispNil));
-
- return(retval);
- }
-
- /*
- ** setup_tlist --
- ** Build a tlist that says which attribute to project to.
- ** This routine is called by ParseFunc() to set up a target list
- ** on a tuple parameter or return value. Due to a bug in 4.0,
- ** it's not possible to refer to system attributes in this case.
- */
- LispValue setup_tlist(attname, relid)
- Name attname;
- ObjectId relid;
- {
- TLE tle;
- LispValue tlist;
- Resdom resnode;
- Var varnode;
- ObjectId typeid;
- int attno;
-
- attno = get_attnum(relid, attname);
- if (attno < 0)
- elog(WARN, "cannot reference attribute %s of tuple params/return values for functions", attname);
-
- typeid = find_atttype(relid, attname);
- resnode = MakeResdom(1, typeid, ISCOMPLEX(typeid),
- tlen(get_id_type(typeid)),
- get_attname(relid, attno),
- NULL /* reskey */,
- NULL /* reskeyop */,
- 0 /* resjunk */);
- varnode = MakeVar(-1, attno, typeid,
- lispCons(lispInteger(-1),
- lispCons(lispInteger(attno),LispNil)),
- 0 /* varslot */);
-
- tle = (LispValue)MakeList(resnode, varnode, -1);
- return(MakeList(tle, -1));
- }
-
- /*
- ** setup_base_tlist --
- ** Build a tlist that extracts a base type from the tuple
- ** returned by the executor.
- */
- LispValue
- setup_base_tlist(typeid)
- ObjectId typeid;
- {
- TLE tle;
- LispValue tlist;
- Resdom resnode;
- Var varnode;
-
- resnode = MakeResdom(1, typeid, ISCOMPLEX(typeid),
- tlen(get_id_type(typeid)),
- (Name) "<noname>", NULL, NULL, 0);
- varnode = MakeVar(-1, 1, typeid,
- lispCons(lispInteger(-1),
- lispCons(lispInteger(1), LispNil)),
- 0);
-
- tle = (LispValue)MakeList(resnode, varnode, -1);
- return (MakeList(tle, -1));
- }
-